/*
  JSON tree construction and walk routines
*/

#define JSON_PRIVATE_
#include "json.h"

json_node* json_node_create()
{
  json_node* node =  (json_node*)calloc(1, sizeof(json_node));
  return node;
}

void json_node_destroy(json_node* node)
{
  json_node* next = NULL;
  if (node == NULL) 
    return;
  while(node->parent) node = node->parent; // Find tree root
  while(node->prev)   node = node->prev;
  while(node) {
    next = node->next;
    if (node->child) {
      node->child->parent = NULL; //Prevent root find
      json_node_destroy(node->child);
    }
    if (node->value) free(node->value);
    if (node->name)  free(node->name);
    if (node) free(node);
    node = next;
  }
}

void json_node_add_next(json_node* node)
{
  if (node == NULL) return;
  node->next = json_node_create();
  node->next->prev = node;
  node->next->parent = node->parent;
}

void json_node_add_child(json_node* node)
{
  if (node == NULL) return;
  node->child = json_node_create();
  node->child->parent = node;
}

json_node* json_node_find(char* name, json_node* node)
{
  if (node == NULL) return NULL;
  json_node* walker = node;
  while(walker){
    if (strcmp(name, walker->name) == 0) return walker;
    walker = walker->next;
  }
  return NULL;
}

void json_node_set_name(json_node* node, char* name, int len)
{
  node->name = (char*)calloc(1, len + 1);
  strncpy(node->name, name, len);
}

void json_node_set_value(json_node* node, void* value, JSON_TYPE_t type, int len)
{
  if (value == NULL) return;
  if(type == TYPE_STRING) node->value = calloc(1, len+1);
  else node->value = calloc(1, len);

  if(node->value) {
    memcpy(node->value, value, len);
    node->type = type;
    node->count = 1;
  }
  else
  {
    //Error...
  }
}

void json_node_add_value(json_node* node, void* value, JSON_TYPE_t type, int len)
{
  if (value == NULL) return;
  if (type != TYPE_STRING) {
    if (node->value != NULL){
      void* tmp = node->value;
      node->value = calloc(1, len*node->count + len);
      memcpy(node->value, tmp, len*node->count);
      free(tmp);
    }
    else {
      node->value = calloc(1, len);
    }
    memcpy((char*)node->value + len*node->count, value, len);
    node->count += 1;
  }
  else {
    //strings...
  }
}
